#!/usr/bin/python
# Copyright 2020 Makani Technologies LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


"""Generate the aio_node_to_ip_address.c file."""

import os
import sys
import textwrap

from makani.avionics.network import network_config


def _WriteIpAddresses(output_dir, script_name, aio_nodes):
  """Write aio_node_to_ip_address.c.

  Args:
    output_dir: The directory in which to output the files.
    script_name: This script's filename.
    aio_nodes: The 'aio_nodes' field of the YAML file.
  """

  parts = [textwrap.dedent("""
      // Generated by {name}; do not edit.

      #include "avionics/network/aio_node_to_ip_address.h"

      #include <assert.h>
      #include <stdbool.h>
      #include <stdint.h>

      #include "avionics/common/network_config.h"
      #include "avionics/network/aio_node.h"

      static uint8_t AioNodeToFinalOctet(AioNode node) {{
        switch (node) {{
          default:
          case kAioNodeForceSigned:
          case kNumAioNodes:
            assert(false);
            return 0;"""[1:]).format(name=script_name)]
  octet_to_node = {}
  for node in aio_nodes:
    octet_to_node[node.ip_octet] = node.enum_name
    parts.append('    case %s:' % node.enum_name)
    parts.append('      return %d;' % node.ip_octet)

  parts.append(textwrap.dedent("""
    }
  }

  // Returns the unicast IP address for a given AioNode.
  //
  // TODO: Renumber all IPs such that each node type gets a range of 20
  // addresses.
  IpAddress AioNodeToIpAddress(AioNode node) {
    bool valid = node > kAioNodeForceSigned && node < kNumAioNodes;
    assert(valid);
    if (!valid) return (IpAddress) {0, 0, 0, 0};
    return (IpAddress) {192, 168, 1, AioNodeToFinalOctet(node)};
  }

  AioNode FinalOctetToAioNode(uint8_t final_octet) {
    switch (final_octet) {"""[1:]))

  for i in sorted(list(octet_to_node)):
    parts.append('    case %s:' % i)
    parts.append('      return %s;' % octet_to_node[i])
  parts.append('    default:')
  parts.append('      return kAioNodeUnknown;')
  parts.append('  }')
  parts.append('}\n')

  file_name = os.path.join(output_dir, 'aio_node_to_ip_address.c')
  with open(file_name, 'w') as f:
    f.write('\n'.join(parts))


def main(argv):
  flags, argv = network_config.ParseGenerationFlags(argv)

  config = network_config.NetworkConfig(flags.network_file)
  script_name = os.path.basename(argv[0])
  _WriteIpAddresses(flags.output_dir, script_name, config.aio_nodes)

if __name__ == '__main__':
  main(sys.argv)
